package com.jwd.avmanager.server;

import com.alibaba.fastjson.JSON;
import com.jwd.avmanager.constant.Constants;
import com.jwd.avmanager.entity.Message;
import com.jwd.avmanager.entity.WebSocketInfo;
import com.jwd.avmanager.parse.ProtocolParserWS;
import com.jwd.avmanager.util.DebugLogger;
import com.jwd.avmanager.util.JsonUtils;
import com.jwd.avmanager.util.ThreadPoolUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.AttributeKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 业务处理器
 *
 * @author LionLi
 */
// TextWebSocketFrame 文本处理
public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    Logger logger = LoggerFactory.getLogger(WebSocketHandler.class);
    private ThreadPoolUtil loginThreads=new ThreadPoolUtil(Runtime.getRuntime().availableProcessors() * 2,
            Runtime.getRuntime().availableProcessors() * 2,"loginThreadPool");
    private ThreadPoolUtil taskThreads=new ThreadPoolUtil();
    public static final AttributeKey<String> URI_ATTRIBUTE_KEY = AttributeKey.valueOf("originalUri");
    /*
经过测试，在 ws 的 uri 后面不能传递参数，不然在 netty 实现 websocket 协议握手的时候会出现断开连接的情况。
针对这种情况在 websocketHandler 之前做了一层 地址过滤，然后重写
request 的 uri，并传入下一个管道中，基本上解决了这个问题。
* */

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        DebugLogger.info(msg  +"--->msg");
        if (null != msg && msg instanceof FullHttpRequest) {

            FullHttpRequest request = (FullHttpRequest) msg;
            System.err.println("调用 channelRead request.uri() [ {} ] "+ request.uri());
            String uri = request.uri();
            ctx.channel().attr(URI_ATTRIBUTE_KEY).set(uri);
            System.err.println("Origin [ {} ] [ {} ] "+ request.headers().get("Origin")+","+ request.headers().get("Host")+","+uri);
            String origin = request.headers().get("Origin");
            if (false) {
                System.err.println("origin 为空 ");
                ctx.close();
            } else {
                if (null != uri && uri.contains(Constants.DEFAULT_WEB_SOCKET_LINK) && uri.contains("?")) {
                    String[] uriArray = uri.split("\\?");
                    for (String s : uriArray) {
                        System.err.println(s);
                    }

                    if (null != uriArray && uriArray.length > 1) {
                        String[] paramsArray = uriArray[1].split("=");
                        if (null != paramsArray && paramsArray.length > 1) {

                            System.err.println(paramsArray[0]);
                            System.err.println(paramsArray[1]);
//                            onlineContainer.putAll(paramsArray[1], ctx);
                        }
                    }
                    request.setUri(Constants.DEFAULT_WEB_SOCKET_LINK);
                } else if(null != uri && uri.contains(Constants.DEFAULT_WEB_SOCKET_LINK2)) {
//                    String s1 = uri.replaceAll(Constants.DEFAULT_WEB_SOCKET_LINK2,"");
//                    String[] uriArray = s1.split("/");
//                    if(uriArray.length==2){
//                        WebSocketInfo  webSocketInfo = new WebSocketInfo();
//                        webSocketInfo.setAccount(uriArray[0]);
//                        webSocketInfo.setPass(uriArray[1]);
//                        webSocketInfo.setCtx(ctx);
//                        DebugLogger.debug(uriArray[0]   +  "[0]");
//                        ClientManager.getInstance().addwebSocketMessage(uriArray[0],webSocketInfo);
//                        System.out.println("123   "+ClientManager.getInstance().getWebSocket(uriArray[0]));
//                    }

                    request.setUri(Constants.DEFAULT_WEB_SOCKET_LINK2);
                } else {
                    System.err.println("不允许 [ {} ] 连接 强制断开"+origin);
                    ctx.close();
                }
            }
        }
        super.channelRead(ctx, msg);
    }


    /**
     * 通道消息读取
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {

        boolean json = JsonUtils.isJsonValid(msg.text());
        DebugLogger.info("收到消息 "+json);
        if (!json){
            ctx.channel().writeAndFlush(new TextWebSocketFrame("服务端发送收到消息 " + "不是json"));
            return;
        }
        String msgText = msg.text();
        String msgText2 = msgText.replaceAll("},\\{", ",");
        Message imageEntity = JSON.parseObject(msgText2, Message.class);
        DebugLogger.info(imageEntity.toString());
        if(imageEntity != null){
            //TODO json解析移除，并且增加线程池
            ctx.channel().eventLoop().execute(new ParseTask(ctx, imageEntity));
        }

    }
 
    /**
     * 连接初始化
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) {
        DebugLogger.info("客户端连接:通道唯一id为 => " + ctx.channel().id().asLongText());
        DebugLogger.info("客户端连接:通道不唯一id为 => " + ctx.channel().id().asShortText());
    }
 
    /**
     * 退出连接
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) {
        DebugLogger.info("客户端断开" + ctx.channel().id().asLongText());
        String surl = ctx.channel().attr(URI_ATTRIBUTE_KEY).get();
        DebugLogger.info("客户端断开URL" + surl);
        if(surl == null){
            DebugLogger.err(logger,"handlerRemoved client is URL null : "+surl);   //客户端请求路径为NULL
            ctx.close();
            return;
        }
        String[] uriArray = surl.split("/");
        if(uriArray.length>=3){
            System.out.println(uriArray[2]+"123");
            String ID = uriArray[2];
            WebSocketInfo webSocketInfo = ClientManager.getInstance().getWebSocketInfo(ID);
            if(webSocketInfo != null){
                ChannelHandlerContext ctx1 = webSocketInfo.getCtx();
                DebugLogger.info("CTXID equals===" + ctx.channel().id().asLongText() +"==="+ctx1.channel().id().asLongText());
                if(ctx1 != null && !(ctx.channel().id().asLongText().equals(ctx1.channel().id().asLongText()))){
                    return;
                }
            }
            ClientManager.getInstance().removeWebSocketMessage(uriArray[2],4,ctx);
        }
    }

    /**
     * 异常处理
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        if(!cause.getMessage().equals("Connection reset by peer")){
            DebugLogger.err(logger,"WebSocketHandler cause.getMessage().equals(Connection reset by peer)");
            cause.printStackTrace();
        }

        DebugLogger.info("客户端异常 " + cause.getMessage());
        DebugLogger.info("客户端异常URL " + ctx.channel().attr(URI_ATTRIBUTE_KEY).get());
        String surl = ctx.channel().attr(URI_ATTRIBUTE_KEY).get();
        if(surl == null){
            DebugLogger.err(logger,"exceptionCaught client is URL null : "+surl); //客户端请求路径为NULL
            ctx.close();
            return;
        }
        String[] uriArray = surl.split("/");
        if(uriArray.length>=3){

            ClientManager.getInstance().removeWebSocketMessage(uriArray[2],10,ctx);
            return;
        }
        //关闭连接
        ctx.close();
    }

    /**
     * 信令解析任务
     */
    private static class ParseTask implements Runnable {
        private Message message;
        private ProtocolParserWS parser;


        public ParseTask(ChannelHandlerContext ctx, Message message) {
            this.message = message;
            parser = new ProtocolParserWS(ctx);
        }

        @Override
        public void run() {
            //TODO json解析放到这里来
            parser.parseMessage(message);
        }
    }
}